/* ------------------------------------------------------------------

 * event.c
 *
 * The event processing functions for Firewall.  An event is an
 * occurence at a particular frame.  Tables of events are loaded by
 * the program for each scene.  These are then handled every frame
 * by processevent().
 * ----------------------------------------------------------------*/

//#define CHUKWUWETA
#define _EVENT_

#define EVENTMEMORYSIZE      4800
#define EVENTFILEMEMORYSIZE  8500
#define EVENTFRAMEMEMORYSIZE 8800

#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include <fcntl.h>
#include <process.h>
#include <stddef.h>

#include "rad.h"
#include "smack.h"
#include "svga.h"
#include "event.h"
#include "player.h"
#include "sound.h"
#include "xenon.h"
#include "sprite.h"
#include "palette.h"
#include "debug.h"
#include "sgdef.h"

#define TRUE 1
#define FALSE 0

/* ------------------------------------------------------------------
    					  Global Variables
 * ------------------------------------------------------------------ */

char		g_cutsceneon = FALSE;
long	   *g_frameevents=(long *) NULL;
long		g_frameeventssize;
TARGET	    g_targstack[MAXTARGETS];
TARGETCLASS g_classtack[MAXCLASSES];

long		LoadEventFile(char *scenename);
void		ProcessFrameEvents(long *frameevents);
void		ProcessSceneEvents(char *scenename);
void		InitSpecConds(void);
long		CheckBranches(long branchnumber);
long		CheckSpecConds(void);

long	   *addDBRN(long *eventstart);
long	   *addEXIT(long *eventstart);
long	   *addESCN(long *eventstart);
long	   *addJUMP(long *eventstart);
long	   *addWSCN(long *eventstart);
long	   *addVIDI(long *eventstart);
long	   *addLINK(long *eventstart);
long	   *addDOZE(long *eventstart);
long	   *addACLU(long *eventstart);
long	   *addSCLU(long *eventstart);
long	   *addAUDI(long *eventstart);
long	   *addBRAN(long *eventstart);
long	   *addDETH(long *eventstart);
long	   *addLEAV(long *eventstart);
long	   *addECUT(long *eventstart);
long	   *addVIEW(long *eventstart);
long	   *addWEAPTOOLCLUE(long *eventstart);
long	   *addTARGET(long *eventstart);
long	   *addSPECCOND(long *eventstart);
long	   *addCUTSCENE(long *eventstart);
long	   *addTARGETCLASS(long *eventstart);
long	   *addFIRETOTARGET(long *eventstart);

extern TARGET  *g_SpritesOnScreen;
extern void SpriteAddOnScreen(long spritenum, TARGET * spritetarg);
extern long g_ecutframe,g_dethframe,g_endcut;
extern long g_currentscenenumber,g_nextscenenumber;
extern char g_typeofdeath;
extern long g_branchframe;
extern char g_killscene;
extern long g_numberofframes;
extern long g_videotoplay;

long		inCutScene = -1;

void		loadevents(void);
void		processevent(long frame);

extern char g_scenetable[][12];
extern char g_videotable[][32];
extern void usePlayer(char *smkfile);

long malloc_size;

/* ------------------------------------------------------------------
 * LoadEventFile()
 *
 * Loads one event file into memory, and returns filesize
 * -----------------------------------------------------------------*/
long LoadEventFile(char *scene)
{
	long fh;
	long  filesize;
	char  name[256];
	struct stat fst;

	if (scene == (char *) NULL)
		return ((long *) NULL);

    GetEventFileMemory(-1); //Initialize event file memory

#ifdef CHUKWUWETA
	sprintf(name, "c:\\data\\%s.dat", scene);
#else
	sprintf(name, "%s\\data\\%s.dat", g_cdrom, scene);
#endif

    if((fh = open(name, O_RDONLY | O_BINARY)) < 0)
	  return(0);

    fstat(fh,&fst);

	if(!(filesize = fst.st_size))
	 return(0);

	read(fh,g_eventfilememory, filesize);
	close(fh);

	return (filesize);
}

/*------------------------------------------------------------------
 * processevent()
 *
 * Processes all the events for a given scene.
 * -----------------------------------------------------------------*/

void ProcessSceneEvents(char *scenename)
{
	long *ep;
	long  esize;
	long  x;
#ifdef DEBUGGING_ON
char errbuf[256];
#endif


	if (scenename == (char *) NULL)
		fatalerror("NULL scenename\n");

	g_numberofframes = g_scenelength[7];//perimeter - the longest!
	GetEventFrameMemory(-1);  //Initialize the event frame memory
	g_frameevents = (long *) GetEventFrameMemory(EVENTFRAMEMEMORYSIZE);

	if (!(esize = LoadEventFile(scenename)))
		fatalerror("Error in loadeventfile\n");
	else ep = g_eventfilememory;

	g_numtargets = -1;
	g_numclasses = -1;
	g_numbranches = -1;

	GetEventMemory(-1);  //Initialize the event memory

	while (esize > 0) 
	 {
		++ep;
		esize -= sizeof(long);  /* Jump over frame number */
		switch (*ep) 
		{
		case 'view':
			ep = addVIEW(ep);
			esize -= (sizeof(VIEW) + sizeof(long));
			break;

		case 'clas':
			ep = addTARGETCLASS(ep);
			esize -= (sizeof(CLAS) + sizeof(long));
			break;

		case 'cond':
			ep = addSPECCOND(ep);
			esize -= (sizeof(COND) + sizeof(long));
			break;

		case 'ctar':
			ep = addTARGET(ep);
			esize -= (sizeof(CTAR) + sizeof(long));
			break;

		case 'weap':
		case 'tool':
		case 'clue':
			ep = addWEAPTOOLCLUE(ep);
			esize -= (sizeof(WEAP) + sizeof(long));
			break;

		case 'fire':
			ep = addFIRETOTARGET(ep);
			esize -= (sizeof(FIRE) + sizeof(long));
			break;

		case 'shot':
			ep = addFIRETOTARGET(ep);
			esize -= (sizeof(FIRE) + sizeof(long));
			break;

		case 'cuts':
			ep = addCUTSCENE(ep);
			esize -= (sizeof(CUTS) + sizeof(long));
			break;

		case 'ecut':
			ep = addECUT(ep);
			esize -= (sizeof(ECUT) + sizeof(long));
			break;

		case 'deth':
			ep = addDETH(ep);
			esize -= (sizeof(DETH) + sizeof(long));
			break;

		case 'leav':
			ep = addLEAV(ep);
			esize -= (sizeof(LEAV) + sizeof(long));
			break;

		case 'doze':
			ep = addDOZE(ep);
			esize -= (sizeof(DOZE) + sizeof(long));
			break;

		case 'link':
			ep = addLINK(ep);
			esize -= (sizeof(LINK) + sizeof(long));
			break;

		case 'bran':
			ep = addBRAN(ep);
			esize -= (sizeof(BRAN) + sizeof(long));
			break;

		case 'vidi':
			ep = addVIDI(ep);
			esize -= (sizeof(VIDI) + sizeof(long));
			break;

		case 'wscn':
			ep = addWSCN(ep);
			esize -= (sizeof(WSCN) + sizeof(long));
			break;

		case 'jump':
			ep = addJUMP(ep);
			esize -= (sizeof(JUMP) + sizeof(long));
			break;

		case 'escn':
			ep = addESCN(ep);
			esize -= (sizeof(ESCN) + sizeof(long));
			break;

		case 'aclu':
			ep = addACLU(ep);
			esize -= (sizeof(ACLU) + sizeof(long));
			break;

		case 'sclu':
			ep = addSCLU(ep);
			esize -= (sizeof(SCLU) + sizeof(long));
			break;

		case 'audi':
			ep = addAUDI(ep);
			esize -= (sizeof(AUDI) + sizeof(long));
			break;

		case 'exit':
			ep = addEXIT(ep);
			esize -= (sizeof(EXIT) + sizeof(long));
			break;

		case 'dbrn':
			ep = addDBRN(ep);
			esize -= (sizeof(DBRN) + sizeof(long));
			break;

		default:
			fatalerror("Unknown event\n");
		}
	}

#if 1 
 if(g_restoregame < MAX_SAVEDGAMES)
  {
    if(g_numtargets != g_savedgame.numtargets)
		fatalerror("ERROR: Corrupt save file. Number of targets does not match scene count\n");

    g_SpritesOnScreen = (TARGET *) NULL;

	for(x =0; x <= g_numtargets; ++x)
	 {
	   g_targstack[x].status.life  =  g_savedgame.targstatus[x].life;
	   g_targstack[x].status.state =  g_savedgame.targstatus[x].state;
	    if(g_savedgame.targstatus[x].isonscreen)
	 	 SpriteAddOnScreen(x, (TARGET *) NULL);
	   g_targstack[x].status.explosioncount = g_savedgame.targstatus[x].explosioncount;
	   g_targstack[x].status.explosionsize = g_savedgame.targstatus[x].explosionsize;
	 }
  }
#endif

#ifdef DEBUGGING_ON
sprintf(errbuf, "Malloced %ld in this scene.\n",malloc_size);
write_trace(errbuf);
#endif
}


/*------------------------------------------------------------------
*ProcesFrameEvents()
*
*Processes all the events for a given Frame.
*-----------------------------------------------------------------*/
void ProcessFrameEvents(long *frameevents)
{
	long *ep = frameevents,
		  esize;
	long  x;

	if (frameevents == (long *) NULL)
		return;

	esize = *frameevents;
	++ep;					   /* Jump past size */
	while (esize > 0) 
	{
		switch (*ep) 
		{
		case 'ctar':
			esize -= 2;
			SpriteAddOnScreen(*(ep + 1), (TARGET *) NULL);
			ep += 2;
			break;

		case 'cton':
			g_cutsceneon = TRUE;
			g_firstcut=TRUE;
			g_endcut=*(ep+1); // where cut scene ends +1
			esize -= 2;
			ep += 2;
			break;

		case 'ctof':
			g_cutsceneon = FALSE;
			g_endcut= -1;
			g_firstcut=FALSE;
			esize -= 1;
			ep += 1;
			break;

		case 'ecut':
			g_ecutframe = *(ep + 1);
			esize -= 2;
			ep += 2;
			break;

		case 'leav':
			g_nextscenenumber = *(ep + 1);
			g_killscene = TRUE;
			esize -= 2;
			ep += 2;
			break;

		case 'audi':
			if (*(ep+2) != -1)
			{
				for (x = 0; x <= g_numtargets; x++)
				{
					if (g_targstack[x].id == *(ep + 2)) 
					{
						if (g_targstack[x].status.state == (short) STATE_ALIVE)
							playSoundFX(*(ep + 1));
					}
				}
			}
			else
			{
				playSoundFX(*(ep + 1));
			}
			esize -= 3;
			ep += 3;
			break;

		case 'deth':
			g_dethframe = *(ep + 1);
			esize -= 2;
			ep += 2;
			break;

		case 'wbrn':
			g_branchwarn = 1;
			esize -= 1;
			ep += 1;
			break;

		case 'bran':
			g_branchwarn = 0;
			if (g_branchframe == -1)
				g_branchframe = CheckBranches(*(ep + 1));
			esize -= 2;
			ep += 2;
			break;

		case 'vidi':
			g_videotoplay = *(ep + 1);
			esize -= 2;
			ep += 2;
			break;
			
		case 'aclu':
			if ((*(ep + 2)) > 0) 
			{
	         if ( (AIL_sample_status(smp[CLUE]) == SMP_DONE) ||
					  (g_currentscenenumber==SC_DATACL && (*(ep +1)==9)) )
	  				// this special case stops the countdown in the secret room
				{
					playClue(*(ep + 1));
					*(ep + 2) -= 1;
				}
			}
			esize -= 3;
			ep += 3;
			break;

		case 'sclu':
			processSpecialClue(*(ep + 1));
			esize -= 2;
			ep += 2;
			break;

		case 'wscn':
		    sprintf(g_blinktxt.blinktext, "%s PORT",
			        g_scenenames[*(ep +1)]);
		    g_blinktxt.numframes = NUMBLINKFRAMES;
			esize -= 2;
			ep += 2;
			break;

		case 'jump':
			g_branchframe = *(ep + 1);
			esize -= 2;
			ep += 2;
			break;

		case 'exit':
			g_killscene = TRUE;
				g_cutplay = *(ep + 1);
			if (*(ep+2) != 99)
				g_nextscenenumber = *(ep + 2);
			esize -= 3;
			ep += 3;
			break;

		case 'escn':
			g_nextscenenumber = *(ep + 1);
			esize -= 2;
			ep += 2;
			break;

		default:
			fatalerror("Bad event on frame\n");
			break;
		}
	}
}

/*-----------------------------------------------------------------------*/
long *addESCN(long *eventstart)
{
	long *evp = eventstart;
	long *newe, *olde, *frameevent;
	short x = -1;

	if (eventstart == (long *) NULL)
		return ((long *) NULL);

	++evp;					  /* Jump past 'escn' */
	if (g_frameevents[*(evp - 2)] != NULL) 
	{				/* Add to new events */
		olde = (long *)g_frameevents[*(evp - 2)];
		x = ((*olde << 2) + (sizeof(long) << 1));
		/* X4			   X2   */
		malloc_size += (4 + (*olde << 2) + (sizeof(long) << 1));
		frameevent = (long *) GetEventMemory((4 + (*olde << 2) + (sizeof(long) << 1)));
		newe = frameevent;
		*(frameevent++) = (*olde + 2);
		for (x = 0; x < *olde; ++x)
			*(frameevent++) = *(olde + 1 + x);  /* transfer old data to new
												 * location */
		*(frameevent) = 'escn';
		*(frameevent + 1) = *evp;	   /* Scene to exit to */
//		free(olde);
		g_frameevents[*(evp - 2)] = newe;
	} 
	else 
	{
		malloc_size += (3 * sizeof(long));
		frameevent = (long *) GetEventMemory((3 * sizeof(long)));
		/* Size of 'CUTS' plus event info size */
		*frameevent = 2;
		*(frameevent + 1) = 'escn';
		*(frameevent + 2) = *evp;	   /* Scene to jump to */
		g_frameevents[*(evp - 2)] = frameevent;
	}

	++evp;
	return (evp);
}

/*-----------------------------------------------------------------------*/
/*-----------------------------------------------------------------------*/
long *addEXIT(long *eventstart)
{
	long *evp = eventstart, *frameevent, *olde, *newe, x, framenum;

	if (eventstart == (long *) NULL)
		return ((long *) NULL);

	framenum = *(evp - 1);
	++evp;					  /* Jump past 'EXIT' */

	if (g_frameevents[framenum] != NULL) 
	{
		olde = (long *)g_frameevents[framenum];
		x = 4 + (*olde << 2) + (3 * sizeof(long));
		frameevent = (long *) GetEventMemory(x);
		malloc_size += x;
		newe = frameevent;
		*(frameevent++) = *olde + 3;
		for (x = 0; x < *olde; ++x)
			*(frameevent++) = *(olde + 1 + x);  /* xfer old data > new location */

		*frameevent = 'exit';
		*(frameevent + 1) = *(evp++);
		*(frameevent + 2) = *(evp++);
//		free(olde);
		g_frameevents[framenum] = newe;
	} 
	else 
	{
		malloc_size += (sizeof(long) << 2);
		frameevent = (long *) GetEventMemory((sizeof(long) << 2));
		/* Size of 'EXIT' plus event info size */
		*frameevent = 3;
		*(frameevent + 1) = 'exit';
		*(frameevent + 2) = *(evp++);
		*(frameevent + 3) = *(evp++);
		g_frameevents[framenum] = frameevent;
	}
	return (evp);
}

/*-----------------------------------------------------------------------*/
/*-----------------------------------------------------------------------*/
long *addVIDI(long *eventstart)
{
	long  *evp = eventstart, *newe, *olde, *frameevent;
	short x = -1;

	if (eventstart == (long *) NULL)
		return ((long *) NULL);

	++evp;					  /* Jump past 'vidi' */
	if (g_frameevents[*(evp - 2)] != NULL) 
	{	/* Add to new events */
		olde = (long *)g_frameevents[*(evp - 2)];
		/* X4				X2   */
		x = 1 + ((*olde << 2) + (sizeof(long) << 1));
		malloc_size += 4 + (*olde << 2) + ((sizeof(long) << 1));
		frameevent = (long *) GetEventMemory(4 + (*olde << 2) + ((sizeof(long) << 1)));
		newe = frameevent;
		*(frameevent++) = (*olde + 2);
		for (x = 0; x < *olde; ++x)
			*(frameevent++) = *(olde + 1 + x);  /* transfer old data to new
												 * location */
		*(frameevent) = 'vidi';
		*(frameevent + 1) = *evp;	   /* Video to play */
//		free(olde);
		g_frameevents[*(evp - 2)] = newe;
	} 
	else 
	{
		malloc_size += (3 * sizeof(long));
		frameevent = (long *) GetEventMemory((3 * sizeof(long)));
		/* Size of 'JUMP' plus event info size */
		*frameevent = 2;
		*(frameevent + 1) = 'vidi';
		*(frameevent + 2) = *evp;	   /* Frame to jump to */
		g_frameevents[*(evp - 2)] = frameevent;
	}

	++evp;
	return (evp);
}

/*-----------------------------------------------------------------------*/
/*-----------------------------------------------------------------------*/

long *addWSCN(long *eventstart)
{
	long  *evp = eventstart, *newe, *olde, *frameevent;
	short  x = -1;

	if (eventstart == (long *) NULL)
		return ((long *) NULL);

	++evp;					  /* Jump past 'wscn' */
	if (g_frameevents[*(evp - 2)] != NULL) 
	{	/* Add to new events */
		olde = (long *)g_frameevents[*(evp - 2)];
		/* X4				X2   */
		x = 1 + ((*olde << 2) + (sizeof(long) << 1));
		malloc_size += 4 + (*olde << 2) + ((sizeof(long) << 1));
		frameevent = (long *) GetEventMemory(4 + (*olde << 2) + ((sizeof(long) << 1)));
		newe = frameevent;
		*(frameevent++) = (*olde + 2);
		for (x = 0; x < *olde; ++x)
			*(frameevent++) = *(olde + 1 + x);  /* transfer old data to new
												 * location */
		*(frameevent) = 'wscn';
		*(frameevent + 1) = *evp;	   /*Scene to warn about*/
//		free(olde);
		g_frameevents[*(evp - 2)] = newe;
	} 
	else 
	{
		malloc_size += (3 * sizeof(long));
		frameevent = (long *) GetEventMemory((3 * sizeof(long)));
		/* Size of 'SWRN' plus event info size */
		*frameevent = 2;
		*(frameevent + 1) = 'wscn';
		*(frameevent + 2) = *evp;	   /*Scene to warn about*/
		g_frameevents[*(evp - 2)] = frameevent;
	}
	++evp;
	return (evp);
}

long *addJUMP(long *eventstart)
{
	long  *evp = eventstart, *newe, *olde, *frameevent;
	short  x = -1;

	if (eventstart == (long *) NULL)
		return ((long *) NULL);

	++evp;					  /* Jump past 'jump' */
	if (g_frameevents[*(evp - 2)] != NULL) 
	{	/* Add to new events */
		olde = (long *)g_frameevents[*(evp - 2)];
		/* X4				X2   */
		x = 1 + ((*olde << 2) + (sizeof(long) << 1));
		malloc_size += 4 + (*olde << 2) + ((sizeof(long) << 1));
		frameevent = (long *) GetEventMemory(4 + (*olde << 2) + ((sizeof(long) << 1)));
		newe = frameevent;
		*(frameevent++) = (*olde + 2);
		for (x = 0; x < *olde; ++x)
			*(frameevent++) = *(olde + 1 + x);  /* transfer old data to new
												 * location */
		*(frameevent) = 'jump';
		*(frameevent + 1) = *evp;	   /* Frame to jump to */
//		free(olde);
		g_frameevents[*(evp - 2)] = newe;
	} 
	else 
	{
		malloc_size += (3 * sizeof(long));
		frameevent = (long *) GetEventMemory((3 * sizeof(long)));
		/* Size of 'CUTS' plus event info size */
		*frameevent = 2;
		*(frameevent + 1) = 'jump';
		*(frameevent + 2) = *evp;	   /* Frame to jump to */
		g_frameevents[*(evp - 2)] = frameevent;
	}
	++evp;
	return (evp);
}

/*-----------------------------------------------------------------------*/
/*-----------------------------------------------------------------------*/
long *addDBRN(long *eventstart)
{
	long *evp = eventstart;

	if (eventstart == (long *) NULL)
		return ((long *) NULL);

	return (evp + ((sizeof(DBRN) >> 2) + (sizeof(long) >> 2)));
}

/*-----------------------------------------------------------------------*/
/*-----------------------------------------------------------------------*/
long *addBRAN(long *eventstart)
{
	long  *evp = eventstart, *newe, *olde, *frameevent;
	long  framenum,wbrnfn;
	short x = -1;


	if (eventstart == (long *) NULL)
		return ((long *) NULL);

	++g_numbranches;

	framenum = *(evp -1);

	if (g_frameevents[*(evp - 1)] != NULL) 
	{				/* Add to new events */
		olde = (long *)g_frameevents[*(evp - 1)];
		/* X4				X2   */
		x = 1 + ((*olde << 2) + (sizeof(long) << 1));
		malloc_size += 4 + ((*olde << 2) + (sizeof(long) << 1));
		frameevent = (long *) GetEventMemory(4 + ((*olde << 2) + (sizeof(long) << 1)));
		newe = frameevent;
		*(frameevent++) = (*olde + 2);
		for (x = 0; x < *olde; ++x)
			*(frameevent++) = *(olde + 1 + x);  /* transfer old data to new
												 * location */
		*(frameevent) = 'bran';
		*(frameevent + 1) = g_numbranches;
//		free(olde);
		g_frameevents[*(evp - 1)] = newe;
	} 
	else 
	{
		malloc_size += (3 * sizeof(long));
		frameevent = (long *) GetEventMemory((3 * sizeof(long)));
		/* Size of 'CUTS' plus event info size */
		*frameevent = 2;
		*(frameevent + 1) = 'bran';
		*(frameevent + 2) = g_numbranches;
		g_frameevents[*(evp - 1)] = frameevent;
	}
	++evp;					  /* Jump past 'bran' */
	g_branchs[g_numbranches].ulx = *(evp++);
	g_branchs[g_numbranches].uly = *(evp++);
	g_branchs[g_numbranches].lrx = *(evp++);
	g_branchs[g_numbranches].lry = *(evp++);
	g_branchs[g_numbranches].branchframe = *(evp++);


   //Add the branch warning
   wbrnfn = ((framenum - 20) < 0) ? 0 : (framenum -20);

	if (g_frameevents[wbrnfn] != NULL) 
	{
		olde = (long *)g_frameevents[wbrnfn];
		x = 1 + (*olde << 2) + sizeof(long);
		malloc_size += 4 + (*olde << 2) + (sizeof(long));
		frameevent = (long *) GetEventMemory(4 + (*olde << 2) + (sizeof(long)));
		newe = frameevent;
		*(frameevent++) = *olde + 1;
		for (x = 0; x < *olde; ++x)
			*(frameevent++) = *(olde + 1 + x);  /* transfer old data to new
												 * location */
		*frameevent = 'wbrn';
//		free(olde);
		g_frameevents[wbrnfn] = newe;
	} 
	else 
	{
		malloc_size += (sizeof(long) << 1);
		frameevent = (long *) GetEventMemory((sizeof(long) << 1));
		/* Size of 'WBRN' plus event info size */
		*frameevent = 1;
		*(frameevent + 1) = 'wbrn';
		g_frameevents[wbrnfn] = frameevent;
	}

	return (evp);
}

/*-----------------------------------------------------------------------*/
/*-----------------------------------------------------------------------*/
long *addLINK(long *eventstart)
{
	long   *evp = eventstart, x;
	TARGET *targtolink, *targ;

	if (eventstart == (long *) NULL)
		return ((long *) NULL);

	++evp;					  /* Jump past 'LINK' */

	for (x = g_numtargets; x >= 0; --x)
		if (g_targstack[x].channel == *evp)
			break;

	if (x < 0)
		fatalerror("Bad link in file\n");

	targtolink = &g_targstack[x];

	for (x = 0; x <= g_numtargets; ++x)
		if ((targtolink->id == g_targstack[x].id) && (targtolink != &g_targstack[x])) 
		{
			if (g_targstack[x].linkhead == (TARGET *) NULL) 
			{
				g_targstack[x].linkhead = &g_targstack[x];
				targtolink->linkhead = &g_targstack[x];
				g_targstack[x].linked = targtolink;
			} 
			else 
			{
				targ = g_targstack[x].linkhead;
				targtolink->linkhead = g_targstack[x].linkhead;
				while (targ != (TARGET *) NULL) 
				{
					if (targ->linked == (TARGET *) NULL) 
					{
						targ->linked = targtolink;
						break;
					} else if ((targ = targ->linked) == (TARGET *) NULL)
						break;  /* Should never get here, just bein' careful */
				}
			}
			break;			  /* Break for da big for */
		}
	evp += 2;
	return (evp);
}

/*-----------------------------------------------------------------------*/
/*-----------------------------------------------------------------------*/
long *addVIEW(long *eventstart)
{
	long *evp = eventstart;

	if (eventstart == (long *) NULL)
		return ((long *) NULL);

	++evp;					  /* Jump past 'VIEW' */
	g_viewmode = *(evp++);

	return (evp);
}

/*-----------------------------------------------------------------------*/
/*-----------------------------------------------------------------------*/
long *addSPECCOND(long *eventstart)
{
	long   *evp = eventstart;
	short  x = -1;
	TARGET targ;

	if (eventstart == (long *) NULL)
		return ((long *) NULL);

	++evp;					  /* Jump past 'cond' */
	targ.startframe = *(evp - 2);
	targ.endframe = *(evp++);
	targ.channel = *(evp++);
	targ.type = *(evp++);
	targ.id = *(evp++);

	for (x = g_numtargets; x >= 0; --x)
		if ((targ.startframe = g_targstack[x].startframe) &&
			(targ.endframe = g_targstack[x].endframe) &&
			(targ.channel = g_targstack[x].channel) &&
			(targ.id = g_targstack[x].id))
			break;

	if(x < 0)
		fatalerror("EVENT : could not find CTAR for COND event\n");

	if (*evp > MAX_SPECCONDS)
		fatalerror("EVENT : Illegal COND in file\n");

	if ((g_spconds[*evp].numspecsprites) > MAX_SPESPRITES)
		fatalerror("EVENT : Number of Special condition sprites exceeds maximum\n");

	g_spconds[*evp].specsprites[g_spconds[*evp].numspecsprites++] = x;
	return (++evp);
}

/*-----------------------------------------------------------------------*/
/*-----------------------------------------------------------------------*/
long *addECUT(long *eventstart)
{
	long  *evp = eventstart, *newe, *olde, *frameevent;
	short x = -1;

	if (eventstart == (long *) NULL)
		return ((long *) NULL);

	if (g_frameevents[*(evp - 1)] != NULL) 
	{						/* Add to new events */
		olde = (long *)g_frameevents[*(evp - 1)];
		/* X4				X2   */
		x = 1 + ((*olde << 2) + (sizeof(long) << 1));
		malloc_size += 4 + ((*olde << 2) + (sizeof(long) << 1));
		frameevent = (long *) GetEventMemory(4 + ((*olde << 2) + (sizeof(long) << 1)));
		newe = frameevent;
		*(frameevent++) = (*olde + 2);
		for (x = 0; x < *olde; ++x)
			*(frameevent++) = *(olde + 1 + x);  /* transfer old data to new
												 * location */
		*(frameevent) = 'ecut';
		*(frameevent + 1) = *(evp + 1);
//		free(olde);
		g_frameevents[*(evp - 1)] = newe;
	} 
	else 
	{
		/* Size of 'ECUT' plus event info size */
		malloc_size += (3 * sizeof(long));
		frameevent = (long *) GetEventMemory((3 * sizeof(long)));

		*frameevent = 2;
		*(frameevent + 1) = 'ecut';
		*(frameevent + 2) = *(evp + 1);
		g_frameevents[*(evp - 1)] = frameevent;
	}

	 g_ecutframe = *(evp + 1);

	evp += 2;
	return (evp);
}

/*-----------------------------------------------------------------------*/
long *addLEAV(long *eventstart)
{
	long  *evp = eventstart, *newe, *olde, *frameevent;
	short  x = -1;

	if (eventstart == (long *) NULL)
		return ((long *) NULL);

	++evp;					  /* Jump past 'leav' */
	if (g_frameevents[*(evp - 2)] != NULL) 
	{	/* Add to new events */
		olde = (long *)g_frameevents[*(evp - 2)];
		/* X4				X2   */
		x = 1 + ((*olde << 2) + (sizeof(long) << 1));
		malloc_size += 4 + (*olde << 2) + ((sizeof(long) << 1));
		frameevent = (long *) GetEventMemory(4 + (*olde << 2) + ((sizeof(long) << 1)));
		newe = frameevent;
		*(frameevent++) = (*olde + 2);
		for (x = 0; x < *olde; ++x)
			*(frameevent++) = *(olde + 1 + x);  /* transfer old data to new
												 * location */
		*(frameevent) = 'leav';
		*(frameevent + 1) = *evp;	   /* Frame to jump to */
//		free(olde);
		g_frameevents[*(evp - 2)] = newe;
	} 
	else 
	{
		malloc_size += (3 * sizeof(long));
		frameevent = (long *) GetEventMemory((3 * sizeof(long)));
		/* Size of 'LEAV' plus event info size */
		*frameevent = 2;
		*(frameevent + 1) = 'leav';
		*(frameevent + 2) = *evp;	   /* Frame to jump to */
		g_frameevents[*(evp - 2)] = frameevent;
	}
	++evp;
	return (evp);
}

/*-----------------------------------------------------------------------*/
#if 0
long *addLEAV(long *eventstart)
{
	long *evp = eventstart, *newe, *olde, *frameevent;
	short x = -1, y;

	if (eventstart == (long *) NULL)
		return ((long *) NULL);
	if (g_frameevents[*(evp - 1)] != NULL) 
	{					/* Add to new events */
		olde = (long *)g_frameevents[*(evp - 1)];
		/* X4				*/
		x = 1 + ((*olde << 2) + sizeof(long));
		malloc_size += 4 + ((*olde << 2) + sizeof(long));
		frameevent = (long *) GetEventMemory(4 + ((*olde << 2) + sizeof(long)));
		newe = frameevent;
		*(frameevent++) = (*olde + 1);
		for (x = 0; x < *olde; ++x)
			*(frameevent++) = *(olde + 1 + x);  /* transfer old data to new
												 * location */
		*(frameevent) = 'leav';
//		free(olde);
		g_frameevents[*(evp - 1)] = newe;
	} 
	else 
	{
		/* Size of 'LEAV' plus event info size */
		/* X2 */
		malloc_size += (sizeof(long) << 1);
		frameevent = (long *) GetEventMemory((sizeof(long) << 1));
		*frameevent = 1;
		*(frameevent + 1) = 'leav';
		g_frameevents[*(evp - 1)] = frameevent;
	}

	evp += 2;
	return (evp);
}
#endif

/*-----------------------------------------------------------------------*/
/*-----------------------------------------------------------------------*/
long *addDETH(long *eventstart)
{
	long  *evp = eventstart, *newe, *olde, *frameevent;
	short x = -1;

	if (eventstart == (long *) NULL)
		return ((long *) NULL);
	if (g_frameevents[*(evp - 1)] != NULL) 
	{					/* Add to new events */
		olde = (long *)g_frameevents[*(evp - 1)];
								/* X4				X2   */
		x = 1 + ((*olde << 2) + (sizeof(long) << 1));
		malloc_size += 4 + ((*olde << 2) + (sizeof(long) << 1));
		frameevent = (long *) GetEventMemory(4 + ((*olde << 2) + (sizeof(long) << 1)));
		newe = frameevent;
		*(frameevent++) = (*olde + 2);
		for (x = 0; x < *olde; ++x)
			*(frameevent++) = *(olde + 1 + x);  /* transfer old data to new
												 * location */
		*(frameevent) = 'deth';
		*(frameevent + 1) = *(evp + 1);
//		free(olde);
		g_frameevents[*(evp - 1)] = newe;
	} 
	else 
	{
		/* Size of 'DETH' plus event info size */
		malloc_size += (3 * sizeof(long));
		frameevent = (long *) GetEventMemory((3 * sizeof(long)));

		*frameevent = 2;
		*(frameevent + 1) = 'deth';
		*(frameevent + 2) = *(evp + 1);
		g_frameevents[*(evp - 1)] = frameevent;
	}

	++g_numdeaths;
	g_deaths[g_numdeaths] = *(evp + 1);

	if(g_dethframe < 0)
	 g_dethframe = g_deaths[g_numdeaths];

	evp += 2;
	return (evp);
}

/*-----------------------------------------------------------------------*/
/*-----------------------------------------------------------------------*/
long  *addWEAPTOOLCLUE(long *eventstart)
{
	long *evp = eventstart, *newe, *olde, *frameevent;
	short  x = -1, y;
	long   framenumb;

	if (eventstart == (long *) NULL)
		return ((long *) NULL);

	++g_numtargets;
	if (g_numtargets == MAXTARGETS)
		fatalerror("EVENT : Maximum number of CTARS exceeded\n");

	framenumb = *(evp - 1);
	if (g_frameevents[*(evp - 1)] != NULL) 
	{					/* Add to new events */
		olde = (long *)g_frameevents[*(evp - 1)];
		/* X4				X2   */
		malloc_size += 4 + ((*olde << 2) + (sizeof(long) << 1));
		frameevent = (long *) GetEventMemory(4 + ((*olde << 2) + (sizeof(long) << 1)));
		newe = frameevent;
		*(frameevent++) = (*olde + 2);
		for (x = 0; x < *olde; ++x)
			*(frameevent++) = *(olde + 1 + x);  /* transfer old data to new
												 * location */
		*(frameevent) = 'ctar';
		*(frameevent + 1) = g_numtargets;
//		free(olde);
		g_frameevents[*(evp - 1)] = newe;
	} 
	else 
	{
		malloc_size += (3 * sizeof(long));
		frameevent = (long *) GetEventMemory((3 * sizeof(long)));
		/* Size of 'CUTS' plus event info size */
		*frameevent = 2;
		*(frameevent + 1) = 'ctar';
		*(frameevent + 2) = g_numtargets;
		g_frameevents[*(evp - 1)] = frameevent;
	}

	g_targstack[g_numtargets].targettype = *(evp++);
	g_targstack[g_numtargets].startframe = *(evp - 2);
	g_targstack[g_numtargets].endframe = *(evp++);
	g_targstack[g_numtargets].channel = *(evp++);
	g_targstack[g_numtargets].type = *(evp++);
	g_targstack[g_numtargets].toolweapclue = *(evp++);
	g_targstack[g_numtargets].id = *(evp++);
    g_targstack[g_numtargets].targetable  = FALSE;
	g_targstack[g_numtargets].status.state = (short) STATE_ALIVE;

	for (x = g_numclasses; x >= 0; --x)
		if (g_classtack[x].type == g_targstack[g_numtargets].type)
			break;
 
	for (y = 0; y < MAXCYBWEAPONS; ++y)
		if(g_classtack[x].pdamage[y])
		 {
	       g_targstack[g_numtargets].targetable  = TRUE;
		   break;
		 }

	if (x < 0)
		fatalerror("CTAR type not in class structure \n");

	g_targstack[g_numtargets].eclass = x;
	g_targstack[g_numtargets].status.life = g_classtack[x].hitpoints;
	g_targstack[g_numtargets].numfires = 0;
	for (y = 0; y < MAXFIRES; ++y)
		g_targstack[g_numtargets].fframes[y] = -1;

	g_targstack[g_numtargets].onscreen = (TARGET *) NULL;
	g_targstack[g_numtargets].status.isonscreen = FALSE;
	g_targstack[g_numtargets].linked	 = (TARGET *) NULL;
	g_targstack[g_numtargets].linkhead = (TARGET *) NULL;

	g_targstack[g_numtargets].status.explosionsize = -1;
	g_targstack[g_numtargets].status.explosioncount = -1;
	return (evp);
}

/*-----------------------------------------------------------------------*/
/*-----------------------------------------------------------------------*/
long *addTARGET(long *eventstart)
{
	long *evp = eventstart, *newe, *olde, *frameevent;
	short  x = -1, y;
	long   framenumb;

	if (eventstart == (long *) NULL)
		return ((long *) NULL);

	++g_numtargets;
	if (g_numtargets == MAXTARGETS)
		fatalerror("EVENT : Maximum number of CTARS exceeded\n");

	framenumb = *(evp - 1);
	if (g_frameevents[*(evp - 1)] != NULL) 
	{					/* Add to new events */
		olde = (long *)g_frameevents[*(evp - 1)];
		/* X4				X2   */
		malloc_size += 4 + ((*olde << 2) + (sizeof(long) << 1));
		frameevent = (long *) GetEventMemory(4 + ((*olde << 2) + (sizeof(long) << 1)));
		newe = frameevent;
		*(frameevent++) = (*olde + 2);
		for (x = 0; x < *olde; ++x)
			*(frameevent++) = *(olde + 1 + x);  /* transfer old data to new
												 * location */
		*(frameevent) = 'ctar';
		*(frameevent + 1) = g_numtargets;
		g_frameevents[*(evp - 1)] = newe;
	} 
	else 
	{
		malloc_size += (3 * sizeof(long));
		frameevent = (long *) GetEventMemory((3 * sizeof(long)));
		/* Size of 'CUTS' plus event info size */
		*frameevent = 2;
		*(frameevent + 1) = 'ctar';
		*(frameevent + 2) = g_numtargets;
		g_frameevents[*(evp - 1)] = frameevent;
	}
	++evp;					  /* Jump past 'ctar' */
	g_targstack[g_numtargets].startframe = *(evp - 2);
	g_targstack[g_numtargets].endframe = *(evp++);
	g_targstack[g_numtargets].channel = *(evp++);
	g_targstack[g_numtargets].type = *(evp++);
	g_targstack[g_numtargets].id = *(evp++);
	g_targstack[g_numtargets].status.state = (short) STATE_ALIVE;
	g_targstack[g_numtargets].targettype = TARGET_ENEMY;
	g_targstack[g_numtargets].toolweapclue = -1;
	g_targstack[g_numtargets].targetable   = FALSE;


	for (x = g_numclasses; x >= 0; --x)
		if (g_classtack[x].type == g_targstack[g_numtargets].type)
			break;

	if (x < 0)
		fatalerror("CTAR type not in class structure \n");

	for (y = 0; y < MAXCYBWEAPONS; ++y)
		if(g_classtack[x].pdamage[y])
		 {
	       g_targstack[g_numtargets].targetable  = TRUE;
		   break;
		 }

	g_targstack[g_numtargets].eclass = x;
	g_targstack[g_numtargets].status.life = g_classtack[x].hitpoints;
	g_targstack[g_numtargets].numfires = 0;
	for (y = 0; y < MAXFIRES; ++y)
		g_targstack[g_numtargets].fframes[y] = -1;

	g_targstack[g_numtargets].status.isonscreen = FALSE;
	g_targstack[g_numtargets].onscreen   = (TARGET *) NULL;
	g_targstack[g_numtargets].linked	 = (TARGET *) NULL;
	g_targstack[g_numtargets].linkhead = (TARGET *) NULL;

	g_targstack[g_numtargets].status.explosionsize  = -1;
	g_targstack[g_numtargets].status.explosioncount = -1;
	return (evp);
}

/*-----------------------------------------------------------------------*/
/*-----------------------------------------------------------------------*/
long *addDOZE(long *eventstart)
{
	long *evp = eventstart;
	long  x;

	if (eventstart == (long *) NULL)
		return ((long *) NULL);

	++evp;					  /* Jump past 'FIRE' */
	for (x = g_numtargets; x >= 0; --x)
		if (g_targstack[x].channel == *evp)
			break;

	if (x < 0)
		fatalerror("EVENT : could not find CTAR for DOZE event\n");

	g_targstack[x].status.state = (short) STATE_SLEEP;

	return (++evp);
}

/*-----------------------------------------------------------------------*/
/*-----------------------------------------------------------------------*/
long  *addFIRETOTARGET(long *eventstart)
{
	long  *evp = eventstart;
	long   x;

	if (eventstart == (long *) NULL)
		return ((long *) NULL);

	++evp;					  /* Jump past 'FIRE' */

	for (x = g_numtargets; x >= 0; --x)
		if (g_targstack[x].channel == *evp)
			break;

	if (x < 0)
		fatalerror("EVENT : could not find CTAR for fire event\n");

	if (g_targstack[x].numfires == (MAXFIRES - 1))
		return (++evp);
	else 
	{
		// g_targstack[x].numfires++;
		g_targstack[x].fframes[g_targstack[x].numfires++] = *(evp - 2);
	}

	return (++evp);
}

/*-----------------------------------------------------------------------*/
/*-----------------------------------------------------------------------*/
long  *addAUDI(long *eventstart)
{
	long *evp = eventstart, *frameevent, *olde, *newe, x;
	long framenum;

	if (eventstart == (long *) NULL)
		return ((long *) NULL);

	framenum = *(evp - 1);
	++evp;					  /* Jump past 'AUDI' */

	if (g_frameevents[framenum] != NULL) 
	{
		olde = (long *)g_frameevents[framenum];
		x = 4 + (*olde << 2) + (3 * sizeof(long));
		frameevent = (long *) GetEventMemory(x);
		malloc_size += x;
		newe = frameevent;
		*(frameevent++) = *olde + 3;
		for (x = 0; x < *olde; ++x)
			*(frameevent++) = *(olde + 1 + x);  /* transfer old data to new
												 * location */

		*frameevent = 'audi';
		*(frameevent + 1) = *(evp++);
		*(frameevent + 2) = *(evp++);
		g_frameevents[framenum] = newe;
	} 
	else 
	{
		malloc_size += (sizeof(long) << 2);
		frameevent = (long *) GetEventMemory((sizeof(long) << 2));
		/* Size of 'AUDI' plus event info size */
		*frameevent = 3;
		*(frameevent + 1) = 'audi';
		*(frameevent + 2) = *(evp++);
		*(frameevent + 3) = *(evp++);
		g_frameevents[framenum] = frameevent;
	}

	return (evp);
}

/*-----------------------------------------------------------------------*/
/*-----------------------------------------------------------------------*/
long  *addACLU(long *eventstart)
{
	long *evp = eventstart, *frameevent, *olde, *newe, x;
	long framenum;

	if (eventstart == (long *) NULL)
		return ((long *) NULL);

	framenum = *(evp - 1);
	++evp;					  /* Jump past 'ACLU' */

	if (g_frameevents[framenum] != NULL) 
	{
		olde = (long *)g_frameevents[framenum];
		x = 4 + (*olde << 2) + (3 * sizeof(long));
		frameevent = (long *) GetEventMemory(x);
		malloc_size += x;
		newe = frameevent;
		*(frameevent++) = *olde + 3;
		for (x = 0; x < *olde; ++x)
			*(frameevent++) = *(olde + 1 + x);  /* transfer old data to new
												 * location */

		*frameevent = 'aclu';
		*(frameevent + 1) = *(evp++);
		*(frameevent + 2) = *(evp++);
		g_frameevents[framenum] = newe;
	} 
	else 
	{
		malloc_size += (sizeof(long) << 2);
		frameevent = (long *) GetEventMemory((sizeof(long) << 2));
		/* Size of 'ACLU' plus event info size */
		*frameevent = 3;
		*(frameevent + 1) = 'aclu';
		*(frameevent + 2) = *(evp++);
		*(frameevent + 3) = *(evp++);
		g_frameevents[framenum] = frameevent;
	}

	return (evp);
}

/*-----------------------------------------------------------------------*/
/*-----------------------------------------------------------------------*/
long *addSCLU(long *eventstart)
{
	long  *evp = eventstart, *newe, *olde, *frameevent;
	short  x = -1;

	if (eventstart == (long *) NULL)
		return ((long *) NULL);

	++evp;					  /* Jump past 'sclu' */
	if (g_frameevents[*(evp - 2)] != NULL) 
	{	/* Add to new events */
		olde = (long *)g_frameevents[*(evp - 2)];
		/* X4				X2   */
		x = 1 + ((*olde << 2) + (sizeof(long) << 1));
		malloc_size += 4 + (*olde << 2) + ((sizeof(long) << 1));
		frameevent = (long *) GetEventMemory(4 + (*olde << 2) + ((sizeof(long) << 1)));
		newe = frameevent;
		*(frameevent++) = (*olde + 2);
		for (x = 0; x < *olde; ++x)
			*(frameevent++) = *(olde + 1 + x);  /* transfer old data to new
												 * location */
		*(frameevent) = 'sclu';
		*(frameevent + 1) = *evp;	   /* Clue file to play */
		g_frameevents[*(evp - 2)] = newe;
	} 
	else 
	{
		malloc_size += (3 * sizeof(long));
		frameevent = (long *) GetEventMemory((3 * sizeof(long)));
		/* Size of 'SCLU' plus event info size */
		*frameevent = 2;
		*(frameevent + 1) = 'sclu';
		*(frameevent + 2) = *evp;	   /* Clue file to play */
		g_frameevents[*(evp - 2)] = frameevent;
	}
	++evp;
	return (evp);
}

/*-----------------------------------------------------------------------*/
/*-----------------------------------------------------------------------*/
long  *addCUTSCENE(long *eventstart)
{
	long  *evp = eventstart, *frameevent, *olde, *newe, x;

	if (eventstart == (long *) NULL)
		return ((long *) NULL);

	++evp;					  /* Jump past 'CUTS' */

	if (g_frameevents[*(evp - 2)] != NULL) 
	{
		olde = (long *)g_frameevents[*(evp - 2)];
		x = 1 + (*olde << 2) + (sizeof(long) << 1);
		malloc_size += 4 + (*olde << 2) + ((sizeof(long) << 1));
		frameevent = (long *) GetEventMemory(4 + (*olde << 2) + ((sizeof(long) << 1)));
		newe = frameevent;
		*(frameevent++) = *olde + 2;
		for (x = 0; x < *olde; ++x)
			*(frameevent++) = *(olde + 1 + x);  /* transfer old data to new
												 * location */
		*frameevent = 'cton';
		*(frameevent+1) = *evp; // adding ending frame
		g_frameevents[*(evp - 2)] = newe;
	} 
	else 
	{
		malloc_size += (3 * sizeof(long));
		frameevent = (long *) GetEventMemory((3 * sizeof(long)));
		/* Size of 'CUTS' plus event info size */
		*frameevent = 2;
		*(frameevent + 1) = 'cton';
		*(frameevent + 2) = *evp; // adding ending frame
		g_frameevents[*(evp - 2)] = frameevent;
	}

	if (g_frameevents[*evp] != NULL) 
	{
		olde = (long *)g_frameevents[*evp];
		malloc_size += 4 + (*olde << 2) + (sizeof(long));
		frameevent = (long *) GetEventMemory(4 + (*olde << 2) + (sizeof(long)));
		newe = frameevent;
		*(frameevent++) = *olde + 1;
		for (x = 0; x < *olde; ++x)
			*(frameevent++) = *(olde + 1 + x); /*transfer old data to new loc*/
		*frameevent = 'ctof';
		g_frameevents[*evp] = newe;
	} 
	else 
	{
		malloc_size += (2 * sizeof(long));
		frameevent = (long *) GetEventMemory((2 * sizeof(long)));
		/* Size of 'CUTS' plus event info size */
		*frameevent = 1;
		*(frameevent + 1) = 'ctof';
		g_frameevents[*evp] = frameevent;
	}
	++evp;
	return (evp);
}

/*-----------------------------------------------------------------------*/
/*-----------------------------------------------------------------------*/
long  *addTARGETCLASS(long *eventstart)
{
	long  *evp = eventstart;
	short  x = -1, y;

	if (eventstart == (long *) NULL)
		return ((long *) NULL);

	if (g_numclasses == MAXCLASSES)
		fatalerror("EVENT : Maximum number of CLASSES exceeded\n");

	for (x = g_numclasses; x >= 0; --x)
		if (g_classtack[x].type == *(eventstart))
			break;

	if (x < 0)
		x = ++g_numclasses;

	++evp;					  /* Jump past 'clas' */
	g_classtack[x].type = *(evp++);
	g_classtack[x].damage = *(evp++);
	g_classtack[x].hitpoints = *(evp++);
	for (y = 0; y < MAXCYBWEAPONS; ++y)
		g_classtack[x].pdamage[y] = *(evp++);

	return (evp);

/* return((long *) ((char *) eventstart + sizeof(CLAS))); */
}


/*-----------------------------------------------------------------------*/
/*-----------------------------------------------------------------------*/
long CheckBranches(long branchnumber)
{
	long playerx, playery,x;

	if (branchnumber > g_numbranches)
		return (-1);

	playerx = g_player.tcx + (short) g_windowx;
	playery = g_player.tcy + (short) g_windowy;

    if((g_currentscenenumber == SC_DATACL) && (branchnumber == 2))
	 {
		 if(g_switched == FALSE)
		  {
		   sprintf(g_blinktxt.blinktext, "ACCESS DENIED");
		   g_blinktxt.numframes = NUMBLINKFRAMES;
		   return(-1);
		  }
		 else if((g_secrroomsolved == TRUE) ||
		         (g_weaps[WP_AIRES].weapaquired == TRUE) ||
		         (g_weaps[WP_AiresMod].weapaquired == TRUE))
			  {
		        sprintf(g_blinktxt.blinktext, "ACCESS NOT REQUIRED");
		        g_blinktxt.numframes = NUMBLINKFRAMES;
		        return(-1);
			  }
	 }


    if((g_currentscenenumber == SC_PDEFEN) && (branchnumber == 1))
	 {
	   for (x = 0; x < g_spconds[SPC_PDEFEN1].numspecsprites; ++x)
		if ((g_targstack[g_spconds[SPC_PDEFEN1].specsprites[x]].status.state) != (short) STATE_DEAD) 
		 break;

		 if(x < g_spconds[SPC_PDEFEN1].numspecsprites)
		  {
		   sprintf(g_blinktxt.blinktext, "ACCESS DENIED");
		   g_blinktxt.numframes = NUMBLINKFRAMES;
		   return(-1);
		  }
	 }

    if((g_currentscenenumber == SC_PDEFEN) && (branchnumber == 2))
	 {
	   for (x = 0; x < g_spconds[SPC_PDEFEN2].numspecsprites; ++x)
		if ((g_targstack[g_spconds[SPC_PDEFEN2].specsprites[x]].status.state) != (short) STATE_DEAD) 
		 break;

		 if(x < g_spconds[SPC_PDEFEN2].numspecsprites)
		  {
		   sprintf(g_blinktxt.blinktext, "ACCESS DENIED");
		   g_blinktxt.numframes = NUMBLINKFRAMES;
		   return (g_branchs[branchnumber + 1].branchframe);
		  }
	 }

    if((g_currentscenenumber == SC_FIREWL) && (branchnumber == 0))
	 {
	   for (x = 0; x < g_spconds[SPC_FIREWAL].numspecsprites; ++x)
		if ((g_targstack[g_spconds[SPC_FIREWAL].specsprites[x]].status.state) != (short) STATE_DEAD) 
		 break;

		 if(x < g_spconds[SPC_FIREWAL].numspecsprites)
		  {
		   sprintf(g_blinktxt.blinktext, "ACCESS DENIED");
		   g_blinktxt.numframes = NUMBLINKFRAMES;
		   return (g_branchs[branchnumber].branchframe);
		  }
		  else return(-1); //Leave firewall
	 }

	if ((playerx > g_branchs[branchnumber].ulx) &&
		(playerx < g_branchs[branchnumber].lrx) &&
		(playery > g_branchs[branchnumber].uly) &&
		(playery < g_branchs[branchnumber].lry))
		return (g_branchs[branchnumber].branchframe);

	return (-1);
}

/*-----------------------------------------------------------------------*/
/*-----------------------------------------------------------------------*/
void InitSpecConds()
{
 memset(g_spconds,0,(MAX_SPECCONDS * sizeof(SPCOND)));
}

/*-----------------------------------------------------------------------*/
/*-----------------------------------------------------------------------*/

#define LASTSPSPRT(x) g_spconds[x].specsprites[g_spconds[x].numspecsprites-1]

long CheckSpecConds()
{
	long   x, y;

	if ((g_currentscenenumber == SC_GRWALL)  && (g_curframe == 465))
	 {
	   g_powrmult =1;
	   for (x = 0; x < g_spconds[SPC_GRWALL].numspecsprites; ++x)
	    {
			if ((g_targstack[g_spconds[SPC_GRWALL].specsprites[x]].status.state) != (short) STATE_DEAD) 
			 ++g_powrmult;
		}
	 }
	else if (g_currentscenenumber == SC_COASTD) 
	{
		if (!g_spconds[SPC_COASTD].numspecsprites)
			return (g_curframe);

		if (g_spconds[SPC_COASTD].solved == TRUE)
			return (g_curframe);

		for (x = 0; x < g_spconds[SPC_COASTD].numspecsprites; ++x)
			if (((g_targstack[g_spconds[SPC_COASTD].specsprites[x]].status.state) == (short) STATE_DEAD) && (!g_targstack[g_spconds[SPC_COASTD].specsprites[x]].status.explosioncount))
			{
				g_spconds[SPC_COASTD].solved = TRUE;
				return (g_ecutframe);
			}
	} 
	else if (g_currentscenenumber == SC_FINALC) 
	{
		if ((g_curframe > 544) && (g_curframe < 565))
		{
		 if (!g_spconds[SPC_FINALC2].numspecsprites)
			return (g_curframe);

        //If the head is dead, the game is over
		if (g_targstack[g_spconds[SPC_FINALC2].specsprites[0]].status.state == (short) STATE_DEAD)
		 {
		    g_videotoplay = VID_POSEND;
			return (g_ecutframe);
		}
       }

		if (g_curframe == 335) 
		{
			for (x = 0; x < g_spconds[SPC_FINALC1].numspecsprites; ++x)
				if ((g_targstack[g_spconds[SPC_FINALC1].specsprites[x]].status.state) != (short) STATE_DEAD)
					break;

			if (x < g_spconds[SPC_FINALC1].numspecsprites) 
			{
				g_typeofdeath = FC_DEATH_BY_CLAP;
				g_player.hitpoints = 0;
				return (g_curframe);
			}
		}
	}
	else if ((g_currentscenenumber == SC_INWALL)  && 
	         (g_curframe > 380) && (g_curframe < 464))
	{
		if (!g_spconds[SPC_INWALL].numspecsprites)
			return (g_curframe);

		if (g_spconds[SPC_INWALL].solved == TRUE)
			return (g_curframe);

		for (x = 0; x < g_spconds[SPC_INWALL].numspecsprites; ++x)
			if ((g_targstack[g_spconds[SPC_INWALL].specsprites[x]].status.state) == (short) STATE_ALIVE) 
			return (g_curframe);

	  return((long) 465); //Yeah, bad practice, but I'm in a hurry
	} 
	else if (g_currentscenenumber == SC_DATACL) 
	{
		if ((g_spconds[SPC_DATACL1].solved == FALSE)  &&
			((g_curframe == g_targstack[LASTSPSPRT(SPC_DATACL1)].endframe) ||
			 (g_curframe == g_targstack[LASTSPSPRT(SPC_DATACL2)].startframe)))
		{			/* Only check on these two frames */
			if (!g_spconds[SPC_DATACL1].numspecsprites)
				return (g_curframe);

			for (x = 0; x < g_spconds[SPC_DATACL1].numspecsprites; ++x)
				if ((g_targstack[g_spconds[SPC_DATACL1].specsprites[x]].status.state) != (short) STATE_REST)
					break;

			if (x == g_spconds[SPC_DATACL1].numspecsprites) 
			{
				if (g_targstack[y = LASTSPSPRT(SPC_DATACL2)].status.state == (short) STATE_SLEEP)
					g_targstack[y = LASTSPSPRT(SPC_DATACL2)].status.state = (short) STATE_ALIVE;

				if (g_targstack[LASTSPSPRT(SPC_DATACL2)].status.isonscreen == FALSE)
					SpriteAddOnScreen(LASTSPSPRT(SPC_DATACL2), (TARGET *) NULL);
			}
			else 
			{
				for (; x > 0; --x)
					g_targstack[g_spconds[SPC_DATACL1].specsprites[x]].status.state = (short) STATE_ALIVE;
			} 

			return (g_curframe);
		}
		// Going towards deleter
		if ((g_curframe >= g_targstack[LASTSPSPRT(SPC_DATACL3)].startframe) &&
			(g_curframe <= g_targstack[LASTSPSPRT(SPC_DATACL3)].endframe)) 
		{

		   if(g_targstack[LASTSPSPRT(SPC_DATACL4)].status.state==(short) STATE_ALIVE)
			 return(g_curframe);

			for (x = 0; x < g_spconds[SPC_DATACL3].numspecsprites; ++x)
				if ((g_targstack[g_spconds[SPC_DATACL3].specsprites[x]].status.state) != (short) STATE_REST)
					break;

			if (x < g_spconds[SPC_DATACL3].numspecsprites)
			 return(g_curframe);

			if (g_targstack[y = LASTSPSPRT(SPC_DATACL4)].status.state == (short) STATE_SLEEP)
				g_targstack[LASTSPSPRT(SPC_DATACL4)].status.state = (short) STATE_ALIVE;

			if (g_targstack[LASTSPSPRT(SPC_DATACL4)].status.isonscreen == FALSE)
				SpriteAddOnScreen(LASTSPSPRT(SPC_DATACL4), (TARGET *) NULL);
		}
	} 
    else if((g_currentscenenumber == SC_CITYLT) && (g_curframe == 696))
	 {
	   for (x = 0; x < g_spconds[SPC_CITYLT].numspecsprites; ++x)
		if ((g_targstack[g_spconds[SPC_CITYLT].specsprites[x]].status.state) == (short) STATE_ALIVE) 
		 break;

		 if(x < g_spconds[SPC_CITYLT].numspecsprites)
		   return(-1);

		   g_switched = TRUE;
	 }
	return (g_curframe);
}

void *GetEventMemory(long amtreq)
{
 static void *freemempntr,*retmempntr;
 char *errormsg1 = "Not enough memory for Firewall event memory\n";
 char *errormsg2 = "Availible Firewall event memory exceeded\n";

 if(g_eventmemory == (void *) NULL)
    if(!(g_eventmemory = (void *) malloc(EVENTMEMORYSIZE)))
      fatalerror(errormsg1);

  if(amtreq < 0)
    {
	 retmempntr  = g_eventmemory;
	 freemempntr = g_eventmemory;
	 memset((char *) g_eventmemory,0,EVENTMEMORYSIZE);
	 return((void *) NULL);
	}

  if(!amtreq)
	return((void *) NULL);

  if(((char *) freemempntr + amtreq)>((char *) g_eventmemory+EVENTMEMORYSIZE))
     fatalerror(errormsg2);

  retmempntr = freemempntr;
  (char*) freemempntr+=amtreq;

  return(retmempntr);
}

void *FreeEventMemory(void)
{
 if(g_eventmemory != (void *) NULL)
  free(g_eventmemory);

 g_eventmemory=(void *) NULL;
}

void *GetEventFileMemory(long amtreq)
{
 static void *freemempntr,*retmempntr;
 char *errormsg1 = "Not enough memory for Firewall event file memory\n";
 char *errormsg2 = "Availible Firewall event file memory exceeded\n";

 if(g_eventfilememory == (void *) NULL)
    if(!(g_eventfilememory = (void *) malloc(EVENTFILEMEMORYSIZE)))
      fatalerror(errormsg1);

  if(amtreq < 0)
    {
	 retmempntr  = g_eventfilememory;
	 freemempntr = g_eventfilememory;
	 memset((char *) g_eventfilememory,0,EVENTFILEMEMORYSIZE);
	 return((void *) NULL);
	}

  if(!amtreq)
	return((void *) NULL);

  if(((char *) freemempntr + amtreq)>((char *) g_eventfilememory+EVENTFILEMEMORYSIZE))
     fatalerror(errormsg2);

  retmempntr = freemempntr;
  (char*) freemempntr+=amtreq;

  return(retmempntr);
}

void *FreeEventFileMemory(void)
{
 if(g_eventfilememory != (void *) NULL)
  free(g_eventfilememory);

 g_eventfilememory=(void *) NULL;
}

void *GetEventFrameMemory(long amtreq)
{
 static void *freemempntr,*retmempntr;
 char *errormsg1 = "Not enough memory for Firewall event frame memory\n";
 char *errormsg2 = "Availible Firewall event frame memory exceeded\n";

 if(g_eventframememory == (void *) NULL)
    if(!(g_eventframememory = (void *) malloc(EVENTFRAMEMEMORYSIZE)))
      fatalerror(errormsg1);

  if(amtreq < 0)
    {
	 retmempntr  = g_eventframememory;
	 freemempntr = g_eventframememory;
	 memset((char *) g_eventframememory,0,EVENTFRAMEMEMORYSIZE);
	 return((void *) NULL);
	}

  if(!amtreq)
	return((void *) NULL);

  if(((char *) freemempntr + amtreq)>((char *) g_eventframememory+EVENTFRAMEMEMORYSIZE))
     fatalerror(errormsg2);

  retmempntr = freemempntr;
  (char*) freemempntr+=amtreq;

  return(retmempntr);
}

void *FreeEventFrameMemory(void)
{
 if(g_eventframememory != (void *) NULL)
  free(g_eventframememory);

 g_eventframememory=(void *) NULL;
}
